/**
 * 
 */
package it.battlehorse.scripting.view;

import it.battlehorse.rcp.sl.annot.Injected;
import it.battlehorse.rcp.sl.annot.Serviceable;
import it.battlehorse.scripting.ScriptSupport;
import it.battlehorse.scripting.ScriptingActivator;
import it.battlehorse.scripting.registry.IScript;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;

import javax.script.ScriptException;

import org.apache.commons.logging.Log;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;


/**
 * Defines an eclipse view which delegates the definition of view contents to a script
 * 
 * @author battlehorse
 *
 */
@Serviceable
public class ScriptProxyView extends ViewPart {
	
	private Log log ; 
	
	@Injected
	public void setLog(Log log) {
		this.log = log;
	} 

	/* the parent composite which will passed to the script to build the UI */
	private Composite scriptParent; 
	
	private Composite parent;
	
	/* A scheduled service which is used by the auto-refresh functionality */
	private ScheduledExecutorService scheduledService;
	
	@Override
	public void init(IViewSite site) throws PartInitException {
		super.init(site);
		scheduledService = new ScheduledThreadPoolExecutor(1);
	}
	
	@Override
	public void dispose() {
		scheduledService.shutdown();
		super.dispose();
	}		
	
	@Override
	public void createPartControl(Composite parent) {
		this.parent = parent;
		
		refresh();
		createToolbar();
	}
	
	@Override
	public void setFocus() {
		// nothing to do		
	}
	
	/* 
	 * Creates the view toolbar
	 */
	private void createToolbar() {
		IToolBarManager mgr = getViewSite().getActionBars().getToolBarManager();
		
		IAction refreshAction = new RefreshAction(this);
        mgr.add(refreshAction);
        mgr.add(new AutoRefreshAction(this,refreshAction));
	}
	
	/**
	 * Refreshes the view contents by reloading the script this view is built upon.
	 *
	 */
	void refresh() {
		log.debug("Refreshing view " + this.getConfigurationElement().getAttribute("id") + "... ");
		
		if (scriptParent != null)
			scriptParent.dispose();
		
		scriptParent = new Composite(parent,SWT.NONE);
		scriptParent.setLayoutData(new GridData(GridData.FILL_BOTH));
		scriptParent.setLayout(new FillLayout(SWT.HORIZONTAL));
		
		IScript script = getScript();
		Map<String,Object> params = new HashMap<String,Object>();
		params.put("parent", scriptParent);
		try {
			new ScriptSupport().runScript(script, params);
		}
		catch(ScriptException se) {
			log.error("An error has occurred while composing the view : " + se.getMessage(),se);
		}
		
		parent.layout();
		parent.redraw();
		parent.update();
		
	}
	
	/**
	 * Returns the scheduled executor service used by the auto-refresh action
	 * 
	 * @return the scheduled executor service used by the auto-refresh action
	 */
	ScheduledExecutorService getScheduledService() {
		return scheduledService;
	}
	
	/**
	 * The script this view is built upon. 
	 * 
	 * @return the script this view is built upon. 
	 */
	IScript getScript() {
		String id = this.getConfigurationElement().getAttribute("id");
		return ScriptingActivator.getDefault().getScriptingRegistry().getScriptFromId(id);
	}
	
	/**
	 * Clears the scheduled executor service
	 *
	 */
	void cycleScheduledService() {
		scheduledService.shutdown();
		scheduledService = new ScheduledThreadPoolExecutor(1);
	}

}
